package client

import (
	"learning/gooop/etcd/raft/config"
	rrpc "learning/gooop/etcd/raft/rpc"
	"net/rpc"
)

type tRaftClient struct {
	cfg   config.IRaftConfig
	peer  config.IRaftNodeConfig
	conn  *rpc.Client
	state iClientState
}

func newRaftClient(cfg config.IRaftConfig, peer config.IRaftNodeConfig, conn *rpc.Client) IRaftClient {
	it := new(tRaftClient)
	it.init(cfg, peer, conn)
	return it
}

func (me *tRaftClient) init(cfg config.IRaftConfig, peer config.IRaftNodeConfig, conn *rpc.Client) {
	me.cfg = cfg
	me.peer = peer
	me.conn = conn

	if conn == nil {
		me.state = newBrokenState(me)
	} else {
		me.state = newConnectedState(me)
	}
	me.state.Start()
}

func (me *tRaftClient) Config() config.IRaftConfig {
	return me.cfg
}

func (me *tRaftClient) Peer() config.IRaftNodeConfig {
	return me.peer
}

func (me *tRaftClient) GetConn() *rpc.Client {
	return me.conn
}

func (me *tRaftClient) SetConn(conn *rpc.Client) {
	me.conn = conn
}

func (me *tRaftClient) HandleStateChanged(state iClientState) {
	me.state = state
	state.Start()
}

func (me *tRaftClient) Heartbeat(cmd *rrpc.HeartbeatCmd, ret *rrpc.HeartbeatRet) error {
	return me.state.Heartbeat(cmd, ret)
}

func (me *tRaftClient) AppendLog(cmd *rrpc.AppendLogCmd, ret *rrpc.AppendLogRet) error {
	return me.state.AppendLog(cmd, ret)
}

func (me *tRaftClient) CommitLog(cmd *rrpc.CommitLogCmd, ret *rrpc.CommitLogRet) error {
	return me.state.CommitLog(cmd, ret)
}

func (me *tRaftClient) RequestVote(cmd *rrpc.RequestVoteCmd, ret *rrpc.RequestVoteRet) error {
	return me.state.RequestVote(cmd, ret)
}

func (me *tRaftClient) ExecuteKVCmd(cmd *rrpc.KVCmd, ret *rrpc.KVRet) error {
	return me.state.ExecuteKVCmd(cmd, ret)
}

func (me *tRaftClient) Ping(cmd *rrpc.PingCmd, ret *rrpc.PingRet) error {
	return me.state.Ping(cmd, ret)
}
